package org.funny.machine32.hardware.processors.cpu;

import com.google.common.collect.Lists;
import org.funny.machine32.base.RegisterEnum;
import org.funny.machine32.hardware.common.HardwareComponentEnum;
import org.funny.machine32.hardware.common.IHardwareComponent;
import org.funny.machine32.hardware.processors.Register;

import java.util.List;

public class CpuRegisterFile implements IHardwareComponent {
    private List<IHardwareComponent> registerFile = initRegisterFile();
    private Register pc = (Register) registerFile.get(32);
    private Register hi = (Register) registerFile.get(33);
    private Register lo = (Register) registerFile.get(34);

    private List<IHardwareComponent> initRegisterFile() {
        List<String> registerNames = Lists.newArrayList(
                RegisterEnum.ZERO.getName(),
                RegisterEnum.AT.getName(),
                RegisterEnum.V0.getName(),
                RegisterEnum.V1.getName(),
                RegisterEnum.A0.getName(),
                RegisterEnum.A1.getName(),
                RegisterEnum.A2.getName(),
                RegisterEnum.A3.getName(),
                RegisterEnum.T0.getName(),
                RegisterEnum.T1.getName(),
                RegisterEnum.T2.getName(),
                RegisterEnum.T3.getName(),
                RegisterEnum.T4.getName(),
                RegisterEnum.T5.getName(),
                RegisterEnum.T6.getName(),
                RegisterEnum.T7.getName(),
                RegisterEnum.S0.getName(),
                RegisterEnum.S1.getName(),
                RegisterEnum.S2.getName(),
                RegisterEnum.S3.getName(),
                RegisterEnum.S4.getName(),
                RegisterEnum.S5.getName(),
                RegisterEnum.S6.getName(),
                RegisterEnum.S7.getName(),
                RegisterEnum.T8.getName(),
                RegisterEnum.T9.getName(),
                RegisterEnum.K0.getName(),
                RegisterEnum.K1.getName(),
                RegisterEnum.GP.getName(),
                RegisterEnum.SP.getName(),
                RegisterEnum.FP.getName(),
                RegisterEnum.RA.getName(),
                RegisterEnum.PC.getName(),
                RegisterEnum.HI.getName(),
                RegisterEnum.LO.getName()
        );

        List<IHardwareComponent> list = Lists.newArrayList();
        for (String registerName : registerNames) {
            list.add(new Register(registerName));
        }
        return list;
    }

    public Register getPc() {
        return pc;
    }

    public Register getHi() {
        return hi;
    }

    public Register getLo() {
        return lo;
    }

    public int getRegisterValue(int index) {
        return ((Register) registerFile.get(index)).read();
    }

    public void updateRegister(int index, int value) {
        ((Register) registerFile.get(index)).write(value);
    }

    @Override
    public String getComponentName() {
        return HardwareComponentEnum.CPU_REGISTER_FILE.getName();
    }

    @Override
    public List<IHardwareComponent> getSubComponents() {
        return registerFile;
    }

    @Override
    public void reset() {
        for (IHardwareComponent component : registerFile) {
            component.reset();
        }
    }
}
